home *** CD-ROM | disk | FTP | other *** search
/ Atari Mega Archive 1 / Atari Mega Archive - Volume 1.iso / gnu / gnulib / libsrc98.zoo / dirent.c < prev    next >
C/C++ Source or Header  |  1993-11-05  |  5KB  |  270 lines

  1. /* POSIX compatible directory access routines for TOS */
  2. /* written by Eric R. Smith and placed in the public domain */
  3.  
  4. #include <assert.h>
  5. #include <stddef.h>
  6. #include <stdlib.h>
  7. #include <stdio.h>
  8. #include <string.h>
  9. #include <types.h>
  10. #include <stat.h>
  11. #include <errno.h>
  12. #include <dirent.h>
  13. #include <osbind.h>
  14. #include <unistd.h>
  15. #include "lib.h"
  16. #include "symdir.h"
  17. #ifndef _COMPILER_H
  18. #include <compiler.h>
  19. #endif
  20.  
  21. static char *shadowed __PROTO((const char *name, SYMDIR *dir));
  22.  
  23. ino_t    __inode;        /* in stat.c */
  24. DIR    *__opendir_chain;    /* ditto */
  25.  
  26. static
  27. char *shadowed(name, dir)
  28.     const char *name;
  29.     SYMDIR *dir;
  30. {
  31.     SYMENTRY *ent;
  32.  
  33.     if (!dir)
  34.         return (char *)0;
  35.  
  36.     ent = dir->s_dir;
  37.     while (ent) {
  38.         if (!strcmp(name, ent->linkto) && (ent->flags & SD_AUTO))
  39.             return ent->linkname;
  40.         ent = ent->next;
  41.     }
  42.     return (char *)0;
  43. }
  44.  
  45. DIR *opendir(_dirname)
  46.     const char *_dirname;
  47. {
  48.     char dirname[FILENAME_MAX];
  49.     char tmpnam[_LIB_NAME_MAX];
  50.     char *t;
  51.     DIR  *dd;
  52.     struct dirent *d, *x, **last;
  53.     SYMENTRY *lent;
  54.     SYMDIR *ldir;
  55.     long r;
  56.     short i = 0;
  57.     struct _dta mydta, *olddta;
  58.  
  59.     _unx2dos(_dirname, dirname);
  60.  
  61. #if 0
  62. /* we should maybe check to see if we're opening a directory */
  63. /* this code doesn't work, though -- Fattrib is dumb */
  64.     if (dirname[0] && (dirname[1] == ':') && !dirname[2]) {
  65.         /* nothing to do */
  66.     } else {
  67.         r = Fattrib(dirname, 0, FA_DIR|FA_HIDDEN|FA_SYSTEM);
  68.         if (r < 0) {
  69.             errno = -r;
  70.             return NULL;
  71.         }
  72.         else if (!(r & FA_DIR)) {
  73.             errno = EPATH;
  74.             return NULL;
  75.         }
  76.     }
  77. #endif
  78.  
  79.     if (!(dd = malloc((size_t)sizeof(DIR)))) {
  80.             errno = ENOMEM;
  81.             return NULL;
  82.     }
  83.  
  84.     olddta = (struct _dta *)Fgetdta();
  85.     Fsetdta(&mydta);
  86.  
  87.     d = x = NULL;
  88.     last = &d;
  89.     dd->D_path = strdup(dirname);
  90.  
  91. /* check for symbolic links in the directory */
  92.     ldir = _read_symdir(dirname);
  93.     if (!ldir)
  94.         goto skip_symlinks;
  95.     lent = ldir->s_dir;
  96.  
  97.     while (lent) {
  98.         x = malloc((size_t)(__DIRENTSIZ(strlen(lent->linkname))));
  99.         if (!x) {
  100.             errno = ENOMEM;
  101.             free(dd->D_path);
  102.             free(dd);
  103.             while(d) {
  104.                 x = d->d_next;
  105.                 free(d);
  106.                 d = x;
  107.             }
  108.             _free_symdir(ldir);
  109.             Fsetdta(olddta);    /* reset dta ++jrb */
  110.             return NULL;
  111.         }
  112.         strcpy(x->d_name, lent->linkname);
  113.         x->d_reclen = x->d_size = strlen(x->d_name);
  114.         x->d_ino = ++__inode;
  115.         x->d_off = i++;
  116.         x->d_next = NULL;
  117.         x->d_date = x->d_time = 0;
  118.         x->d_attribute = 0xff;    /* mark symbolic link */
  119.         *last = x;
  120.         last = &x->d_next;
  121.         lent = lent->next;
  122.     }
  123.  
  124. /* OK, so much for the symbolic links. Now for the real directories */
  125.  
  126. skip_symlinks:
  127.  
  128.     strcat(dirname, "\\*.*");
  129.     if ((r = Fsfirst(dirname, FA_SYSTEM|FA_HIDDEN|FA_DIR)) != 0) {
  130.     /* report an error unless dirname is a root directory     */
  131.     /* (all other valid directories have '.' and '..' in them */
  132.             if (!*dirname || strcmp(dirname+1, "\\*.*")) {
  133.                     errno = -r;
  134.             while (d) {
  135.                 x = d->d_next;
  136.                 free(d);
  137.                 d = x;
  138.             }
  139.             free(dd->D_path);
  140.                     free(dd);
  141.                     dd = NULL;
  142.         }
  143.     } else {        /* Fsfirst worked OK */
  144.         do {
  145.                 _dos2unx(mydta.dta_name, tmpnam);
  146.         /* skip the symbolic directory itself if we're supposed to */
  147.             if (_lHIDE && _lOK && !strcmp(_lDIR, tmpnam))
  148.                 continue;
  149.         /* check for files being hidden by auto symlinks */
  150.             if (_lAUTO && (t = shadowed(tmpnam, ldir))) {
  151.                 for (x = d; x; x = x->d_next)
  152.                     if (!strcmp(x->d_name, t))
  153.                         break;
  154.                 assert(x != 0);
  155.         /* put the real file's info in the structure */
  156.                 goto tos_fill;
  157.             }
  158.             x = malloc((size_t)(__DIRENTSIZ(strlen(tmpnam))));
  159.                 if (!x) {
  160.                 errno = ENOMEM;
  161.                 while (d) {
  162.                     x = d->d_next;
  163.                     free(d);
  164.                     d = x;
  165.                 }
  166.                 free(dd->D_path);
  167.                 free(dd);
  168.                 dd = NULL;
  169.                 break;
  170.                 }
  171.             strcpy(x->d_name, tmpnam);
  172.                 x->d_ino = ++__inode; /* make sure no two are equal */
  173.                 x->d_off = i++;
  174. /* I don't know what d_reclen means on Unix, but for TOS we might as well
  175.    stuff the string length in here (so sys/dir.h can be more like BSD) */
  176.                 x->d_reclen = strlen(x->d_name);
  177.             x->d_next = NULL;
  178.             *last = x;
  179.             last = &x->d_next;
  180. tos_fill:
  181. /* fill in TOS specific stuff so stat can find it later */
  182.             x->d_time = mydta.dta_time;
  183.             x->d_date = mydta.dta_date;
  184.             x->d_attribute = mydta.dta_attribute;
  185.             x->d_size = mydta.dta_size;
  186.         } while (!Fsnext());
  187.     }
  188.  
  189.     Fsetdta(olddta);
  190.     if (dd) {
  191.         dd->D_list = dd->D_curpos = d;
  192.         dd->D_nxtdir = __opendir_chain;
  193.         __opendir_chain = dd;
  194.     }
  195.     _free_symdir(ldir);
  196.     return dd;
  197. }
  198.  
  199. struct dirent *readdir(dirp)
  200.     DIR *dirp;
  201. {
  202.     struct dirent *x;
  203.  
  204.     if (!dirp) return NULL;
  205.  
  206.     x = dirp->D_curpos;
  207.     if (x) dirp->D_curpos = x->d_next;
  208.     return x;
  209. }
  210.  
  211. off_t telldir(dirp)
  212.        DIR *dirp;
  213. {
  214.     struct dirent *x = dirp->D_curpos;
  215.     if (x)
  216.         return x->d_off;
  217.     else
  218.         return -1;
  219. }
  220.  
  221. void seekdir(dirp, loc)
  222.     DIR *dirp;
  223.     off_t loc;
  224. {
  225.     struct dirent *x;
  226.  
  227.     x = dirp->D_list;
  228.     while (x && x->d_off != loc)
  229.         x = x->d_next;
  230.     dirp->D_curpos = x;
  231. }
  232.  
  233. void rewinddir(dirp)
  234.        DIR *dirp;
  235. {
  236.     dirp->D_curpos = dirp->D_list;
  237. }
  238.  
  239. int closedir(dirp)
  240.     DIR *dirp;
  241. {
  242.     struct dirent *x, *oldx;
  243.     DIR **old, *nxt;
  244.  
  245.     if (!dirp) return -1;
  246.  
  247.     if (dirp->D_path)
  248.         free(dirp->D_path);
  249.  
  250.     for (x = dirp->D_list; x; ) {
  251.         oldx = x;
  252.         x = x->d_next;
  253.         free(oldx);
  254.     }
  255. /* unlink from __opendir_chain */
  256.     old = &__opendir_chain;
  257.     nxt = *old;
  258.     while (nxt) {
  259.         if (nxt == dirp) {
  260.             *old = nxt->D_nxtdir;
  261.             nxt->D_nxtdir = 0;
  262.             break;
  263.         }
  264.         old = &nxt->D_nxtdir;
  265.         nxt = *old;
  266.     }
  267.     free(dirp);
  268.     return 0;
  269. }
  270.